package com.tony.mulitithread.utils;

import com.alibaba.excel.util.NumberUtils;
import org.apache.poi.ss.formula.functions.T;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

/**
 * 多线程查全表通用工具类.
 */
//多线程批量查询up主2的法2
public class ThreadPoolUtils {

    /**
     * 定义十个线程
     */
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());

    /**
     * 估算Arraylist 最适合初始容量
     *
     * @param num
     * @return
     */
    public static int arrayListRightSize(int num) {
        if (num > 0) {
            //向上取整
            return (int) Math.ceil(1.5 * num);
        } else {
            return 10;
        }
    }

    /**
     * 多线程查全表(通用)
     * ThreadPoolExecutor线程池方法
     *
     * @param totalNum             总条数
     * @param threadTableDataQuery 查询方法(需要新建接口类)
     * @return
     */
    public static List<T> threadPool(int totalNum, ThreadTableDataQuery threadTableDataQuery) throws Exception {
        //将ArrayList转换为线程安全的SynchronizedList
        List<T> result = Collections.synchronizedList(new ArrayList<>(arrayListRightSize(totalNum)));
//        List<T> result = new CopyOnWriteArrayList<>();
        //如果总数据量超过10，就会启动多线程异步处理数据；否则直接在当前线程中处理数据。
        if (totalNum > 10) {
            //这里是将数据分成10份，计算每份的条数。remainder表示数据除以10的余数，size表示每份的数据条数，如果除10取余大于0，每次查询totalNum / 10 + 1条。
            int remainder = totalNum % 10;
            int size = remainder > 0 ? totalNum / 10 + 1 : totalNum / 10;
            CountDownLatch downLatch = new CountDownLatch(10);
            for (int i = 0; i < 10; i++) {
                int page = i * size;
                //这里通过线程池的submit方法提交任务，使用Lambda表达式来处理数据查询。
                executor.submit(() -> {
                    try {
                        result.addAll(threadTableDataQuery.selectTableData(page, size));
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        downLatch.countDown();
                    }
                });
            }
            try {
                //使用CountDownLatch来等待所有线程处理完毕。
                downLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            result.addAll(threadTableDataQuery.selectTableData(0, 10));
        }
        return result;
    }

}
